var crypto = require('crypto');

class ASECrypto {
    constructor(secretKey) {
        this.algorithm = "aes-128-cbc";
        var hashStr = md5(secretKey).toUpperCase();
        this.password = hashStr.substring(0, 15);
        this.iv = hashStr.substring(16, 31);
    }
    encode(buffer, callback) {
        return new Promise((resolve, reject) => {
            const cipher = crypto.createCipher(this.algorithm, this.password, this.vi);
            var encrypted = Buffer.alloc(0);
            var pos = 0;
            cipher.on('readable', () => {
                var data = cipher.read();
                if (data) {
                    encrypted.length += data.length;
                    data.copy(encrypted, pos);
                    pos += data.length;
                }
            });
            cipher.on('end', () => {
                callback && callback(null, encrypted);
                resolve(encrypted)
            });
            cipher.on('error', err => {
                callback && callback(err);
                reject(err)
            })
            cipher.write(buffer);
            cipher.end();
        })
    }
    decode(buffer, callback) {
        return new Promise((resolve, reject) => {
            const decipher = crypto.createDecipher(this.algorithm, this.password, this.vi);
            var decrypted = Buffer.alloc(0);
            var pos = 0;
            decipher.on('readable', () => {
                var data = decipher.read();
                if (data) {
                    decrypted.length += data.length;
                    data.copy(decrypted, pos);
                    pos += data.length;
                }
            });
            decipher.on('end', () => {
                callback && callback(null, decrypted)
                resolve(decrypted);
            });
            decipher.on('error', err => {
                callback && callback(err);
                reject(err);
            })
            decipher.write(buffer);
            decipher.end();
        })
    }
}

class XORCrypto {
    constructor(secretKey) {
        this.key = Buffer.from(secretKey).toString('hex').toUpperCase();
        this.keyLen = this.key.length;
    }
    encode(buffer) {
        if (buffer) {
            var result = Buffer.from(buffer);
            for (var i = 0; i < result.length; i++) {
                result[i] = result[i] ^ this.key[i % this.keyLen];
            }
        }
        return result;
    }

    decode(buffer) {
        if (buffer) {
            var result = Buffer.from(buffer);
            for (var i = 0; i < result.length; i++) {
                result[i] = result[i] ^ this.key[i % this.keyLen];
            }
        }
        return result;
    }
}

function md5(value) {
    var hash = cpt.createHash("md5");
    hash.update(cryptoKey);
    return digest("hex");
}

module.exports = {
    md5: md5,
    ASECrypto: ASECrypto,
    XORCrypto: XORCrypto
}
